<!-- HTML header for doxygen 1.8.6-->
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<meta name="generator" content="Doxygen 1.8.13"/>
<title>OpenCV: Template Matching</title>
<link href="../../opencv.ico" rel="shortcut icon" type="image/x-icon" />
<link href="../../tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="../../jquery.js"></script>
<script type="text/javascript" src="../../dynsections.js"></script>
<script type="text/javascript" src="../../tutorial-utils.js"></script>
<link href="../../search/search.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="../../search/searchdata.js"></script>
<script type="text/javascript" src="../../search/search.js"></script>
<script type="text/x-mathjax-config">
  MathJax.Hub.Config({
    extensions: ["tex2jax.js", "TeX/AMSmath.js", "TeX/AMSsymbols.js"],
    jax: ["input/TeX","output/HTML-CSS"],
});
//<![CDATA[
MathJax.Hub.Config(
{
  TeX: {
      Macros: {
          matTT: [ "\\[ \\left|\\begin{array}{ccc} #1 & #2 & #3\\\\ #4 & #5 & #6\\\\ #7 & #8 & #9 \\end{array}\\right| \\]", 9],
          fork: ["\\left\\{ \\begin{array}{l l} #1 & \\mbox{#2}\\\\ #3 & \\mbox{#4}\\\\ \\end{array} \\right.", 4],
          forkthree: ["\\left\\{ \\begin{array}{l l} #1 & \\mbox{#2}\\\\ #3 & \\mbox{#4}\\\\ #5 & \\mbox{#6}\\\\ \\end{array} \\right.", 6],
          forkfour: ["\\left\\{ \\begin{array}{l l} #1 & \\mbox{#2}\\\\ #3 & \\mbox{#4}\\\\ #5 & \\mbox{#6}\\\\ #7 & \\mbox{#8}\\\\ \\end{array} \\right.", 8],
          vecthree: ["\\begin{bmatrix} #1\\\\ #2\\\\ #3 \\end{bmatrix}", 3],
          vecthreethree: ["\\begin{bmatrix} #1 & #2 & #3\\\\ #4 & #5 & #6\\\\ #7 & #8 & #9 \\end{bmatrix}", 9],
          cameramatrix: ["#1 = \\begin{bmatrix} f_x & 0 & c_x\\\\ 0 & f_y & c_y\\\\ 0 & 0 & 1 \\end{bmatrix}", 1],
          distcoeffs: ["(k_1, k_2, p_1, p_2[, k_3[, k_4, k_5, k_6 [, s_1, s_2, s_3, s_4[, \\tau_x, \\tau_y]]]]) \\text{ of 4, 5, 8, 12 or 14 elements}"],
          distcoeffsfisheye: ["(k_1, k_2, k_3, k_4)"],
          hdotsfor: ["\\dots", 1],
          mathbbm: ["\\mathbb{#1}", 1],
          bordermatrix: ["\\matrix{#1}", 1]
      }
  }
}
);
//]]>
</script><script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js"></script>
<link href="../../doxygen.css" rel="stylesheet" type="text/css" />
<link href="../../stylesheet.css" rel="stylesheet" type="text/css"/>
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<!--#include virtual="/google-search.html"-->
<table cellspacing="0" cellpadding="0">
 <tbody>
 <tr style="height: 56px;">
  <td id="projectlogo"><img alt="Logo" src="../../opencv-logo-small.png"/></td>
  <td style="padding-left: 0.5em;">
   <div id="projectname">OpenCV
   &#160;<span id="projectnumber">4.5.2</span>
   </div>
   <div id="projectbrief">Open Source Computer Vision</div>
  </td>
 </tr>
 </tbody>
</table>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.8.13 -->
<script type="text/javascript">
var searchBox = new SearchBox("searchBox", "../../search",false,'Search');
</script>
<script type="text/javascript" src="../../menudata.js"></script>
<script type="text/javascript" src="../../menu.js"></script>
<script type="text/javascript">
$(function() {
  initMenu('../../',true,false,'search.php','Search');
  $(document).ready(function() { init_search(); });
});
</script>
<div id="main-nav"></div>
<!-- window showing the filter options -->
<div id="MSearchSelectWindow"
     onmouseover="return searchBox.OnSearchSelectShow()"
     onmouseout="return searchBox.OnSearchSelectHide()"
     onkeydown="return searchBox.OnSearchSelectKey(event)">
</div>

<!-- iframe showing the search results (closed by default) -->
<div id="MSearchResultsWindow">
<iframe src="javascript:void(0)" frameborder="0" 
        name="MSearchResults" id="MSearchResults">
</iframe>
</div>

<div id="nav-path" class="navpath">
  <ul>
<li class="navelem"><a class="el" href="../../d6/d00/tutorial_py_root.html">OpenCV-Python Tutorials</a></li><li class="navelem"><a class="el" href="../../d2/d96/tutorial_py_table_of_contents_imgproc.html">Image Processing in OpenCV</a></li>  </ul>
</div>
</div><!-- top -->
<div class="header">
  <div class="headertitle">
<div class="title">Template Matching </div>  </div>
</div><!--header-->
<div class="contents">
<div class="textblock"><h2>Goals </h2>
<p>In this chapter, you will learn</p><ul>
<li>To find objects in an image using Template Matching</li>
<li>You will see these functions : <b><a class="el" href="../../df/dfb/group__imgproc__object.html#ga586ebfb0a7fb604b35a23d85391329be" title="Compares a template against overlapped image regions. ">cv.matchTemplate()</a></b>, <b><a class="el" href="../../d2/de8/group__core__array.html#gab473bf2eb6d14ff97e89b355dac20707" title="Finds the global minimum and maximum in an array. ">cv.minMaxLoc()</a></b></li>
</ul>
<h2>Theory </h2>
<p>Template Matching is a method for searching and finding the location of a template image in a larger image. OpenCV comes with a function <b><a class="el" href="../../df/dfb/group__imgproc__object.html#ga586ebfb0a7fb604b35a23d85391329be" title="Compares a template against overlapped image regions. ">cv.matchTemplate()</a></b> for this purpose. It simply slides the template image over the input image (as in 2D convolution) and compares the template and patch of input image under the template image. Several comparison methods are implemented in OpenCV. (You can check docs for more details). It returns a grayscale image, where each pixel denotes how much does the neighbourhood of that pixel match with template.</p>
<p>If input image is of size (WxH) and template image is of size (wxh), output image will have a size of (W-w+1, H-h+1). Once you got the result, you can use <b><a class="el" href="../../d2/de8/group__core__array.html#gab473bf2eb6d14ff97e89b355dac20707" title="Finds the global minimum and maximum in an array. ">cv.minMaxLoc()</a></b> function to find where is the maximum/minimum value. Take it as the top-left corner of rectangle and take (w,h) as width and height of the rectangle. That rectangle is your region of template.</p>
<dl class="section note"><dt>Note</dt><dd>If you are using <a class="el" href="../../df/dfb/group__imgproc__object.html#gga3a7850640f1fe1f58fe91a2d7583695dab65c042ed62c9e9e095a1e7e41fe2773">cv.TM_SQDIFF</a> as comparison method, minimum value gives the best match.</dd></dl>
<h2>Template Matching in OpenCV </h2>
<p>Here, as an example, we will search for Messi's face in his photo. So I created a template as below:</p>
<div class="image">
<img src="../../messi_face.jpg" alt="messi_face.jpg"/>
<div class="caption">
image</div></div>
<p> We will try all the comparison methods so that we can see how their results look like: </p><div class="fragment"><div class="line"><span class="keyword">import</span> cv2 <span class="keyword">as</span> cv</div><div class="line"><span class="keyword">import</span> numpy <span class="keyword">as</span> np</div><div class="line"><span class="keyword">from</span> matplotlib <span class="keyword">import</span> pyplot <span class="keyword">as</span> plt</div><div class="line"></div><div class="line">img = <a class="code" href="../../d4/da8/group__imgcodecs.html#ga288b8b3da0892bd651fce07b3bbd3a56">cv.imread</a>(<span class="stringliteral">&#39;messi5.jpg&#39;</span>,0)</div><div class="line">img2 = img.copy()</div><div class="line">template = <a class="code" href="../../d4/da8/group__imgcodecs.html#ga288b8b3da0892bd651fce07b3bbd3a56">cv.imread</a>(<span class="stringliteral">&#39;template.jpg&#39;</span>,0)</div><div class="line">w, h = template.shape[::-1]</div><div class="line"></div><div class="line"><span class="comment"># All the 6 methods for comparison in a list</span></div><div class="line">methods = [<span class="stringliteral">&#39;cv.TM_CCOEFF&#39;</span>, <span class="stringliteral">&#39;cv.TM_CCOEFF_NORMED&#39;</span>, <span class="stringliteral">&#39;cv.TM_CCORR&#39;</span>,</div><div class="line">            <span class="stringliteral">&#39;cv.TM_CCORR_NORMED&#39;</span>, <span class="stringliteral">&#39;cv.TM_SQDIFF&#39;</span>, <span class="stringliteral">&#39;cv.TM_SQDIFF_NORMED&#39;</span>]</div><div class="line"></div><div class="line"><span class="keywordflow">for</span> meth <span class="keywordflow">in</span> methods:</div><div class="line">    img = img2.copy()</div><div class="line">    method = eval(meth)</div><div class="line"></div><div class="line">    <span class="comment"># Apply template Matching</span></div><div class="line">    res = <a class="code" href="../../df/dfb/group__imgproc__object.html#ga586ebfb0a7fb604b35a23d85391329be">cv.matchTemplate</a>(img,template,method)</div><div class="line">    min_val, max_val, min_loc, max_loc = <a class="code" href="../../d2/de8/group__core__array.html#ga8873b86a29c5af51cafdcee82f8150a7">cv.minMaxLoc</a>(res)</div><div class="line"></div><div class="line">    <span class="comment"># If the method is TM_SQDIFF or TM_SQDIFF_NORMED, take minimum</span></div><div class="line">    <span class="keywordflow">if</span> method <span class="keywordflow">in</span> [cv.TM_SQDIFF, cv.TM_SQDIFF_NORMED]:</div><div class="line">        top_left = min_loc</div><div class="line">    <span class="keywordflow">else</span>:</div><div class="line">        top_left = max_loc</div><div class="line">    bottom_right = (top_left[0] + w, top_left[1] + h)</div><div class="line"></div><div class="line">    <a class="code" href="../../d6/d6e/group__imgproc__draw.html#gac865734d137287c0afb7682ff7b3db23">cv.rectangle</a>(img,top_left, bottom_right, 255, 2)</div><div class="line"></div><div class="line">    plt.subplot(121),plt.imshow(res,cmap = <span class="stringliteral">&#39;gray&#39;</span>)</div><div class="line">    plt.title(<span class="stringliteral">&#39;Matching Result&#39;</span>), plt.xticks([]), plt.yticks([])</div><div class="line">    plt.subplot(122),plt.imshow(img,cmap = <span class="stringliteral">&#39;gray&#39;</span>)</div><div class="line">    plt.title(<span class="stringliteral">&#39;Detected Point&#39;</span>), plt.xticks([]), plt.yticks([])</div><div class="line">    plt.suptitle(meth)</div><div class="line"></div><div class="line">    plt.show()</div></div><!-- fragment --><p> See the results below:</p>
<ul>
<li><a class="el" href="../../df/dfb/group__imgproc__object.html#gga3a7850640f1fe1f58fe91a2d7583695dac5babb7dfda59544e3e31ea928f8cb16">cv.TM_CCOEFF</a></li>
</ul>
<div class="image">
<img src="../../template_ccoeff_1.jpg" alt="template_ccoeff_1.jpg"/>
<div class="caption">
image</div></div>
<ul>
<li><a class="el" href="../../df/dfb/group__imgproc__object.html#gga3a7850640f1fe1f58fe91a2d7583695dac6677e2af5e0fae82cc5339bfaef5038">cv.TM_CCOEFF_NORMED</a></li>
</ul>
<div class="image">
<img src="../../template_ccoeffn_2.jpg" alt="template_ccoeffn_2.jpg"/>
<div class="caption">
image</div></div>
<ul>
<li><a class="el" href="../../df/dfb/group__imgproc__object.html#gga3a7850640f1fe1f58fe91a2d7583695da5be00b45a4d99b5e42625b4400bfde65">cv.TM_CCORR</a></li>
</ul>
<div class="image">
<img src="../../template_ccorr_3.jpg" alt="template_ccorr_3.jpg"/>
<div class="caption">
image</div></div>
<ul>
<li><a class="el" href="../../df/dfb/group__imgproc__object.html#gga3a7850640f1fe1f58fe91a2d7583695daf9c3ab9296f597ea71f056399a5831da">cv.TM_CCORR_NORMED</a></li>
</ul>
<div class="image">
<img src="../../template_ccorrn_4.jpg" alt="template_ccorrn_4.jpg"/>
<div class="caption">
image</div></div>
<ul>
<li><a class="el" href="../../df/dfb/group__imgproc__object.html#gga3a7850640f1fe1f58fe91a2d7583695dab65c042ed62c9e9e095a1e7e41fe2773">cv.TM_SQDIFF</a></li>
</ul>
<div class="image">
<img src="../../template_sqdiff_5.jpg" alt="template_sqdiff_5.jpg"/>
<div class="caption">
image</div></div>
<ul>
<li><a class="el" href="../../df/dfb/group__imgproc__object.html#gga3a7850640f1fe1f58fe91a2d7583695da5382c8f9df87e87cf1e9f9927dc3bc31">cv.TM_SQDIFF_NORMED</a></li>
</ul>
<div class="image">
<img src="../../template_sqdiffn_6.jpg" alt="template_sqdiffn_6.jpg"/>
<div class="caption">
image</div></div>
<p> You can see that the result using <b><a class="el" href="../../df/dfb/group__imgproc__object.html#gga3a7850640f1fe1f58fe91a2d7583695da5be00b45a4d99b5e42625b4400bfde65">cv.TM_CCORR</a></b> is not good as we expected.</p>
<h2>Template Matching with Multiple Objects </h2>
<p>In the previous section, we searched image for Messi's face, which occurs only once in the image. Suppose you are searching for an object which has multiple occurrences, <b><a class="el" href="../../d2/de8/group__core__array.html#gab473bf2eb6d14ff97e89b355dac20707" title="Finds the global minimum and maximum in an array. ">cv.minMaxLoc()</a></b> won't give you all the locations. In that case, we will use thresholding. So in this example, we will use a screenshot of the famous game <b>Mario</b> and we will find the coins in it. </p><div class="fragment"><div class="line"><span class="keyword">import</span> cv2 <span class="keyword">as</span> cv</div><div class="line"><span class="keyword">import</span> numpy <span class="keyword">as</span> np</div><div class="line"><span class="keyword">from</span> matplotlib <span class="keyword">import</span> pyplot <span class="keyword">as</span> plt</div><div class="line"></div><div class="line">img_rgb = <a class="code" href="../../d4/da8/group__imgcodecs.html#ga288b8b3da0892bd651fce07b3bbd3a56">cv.imread</a>(<span class="stringliteral">&#39;mario.png&#39;</span>)</div><div class="line">img_gray = <a class="code" href="../../d8/d01/group__imgproc__color__conversions.html#ga397ae87e1288a81d2363b61574eb8cab">cv.cvtColor</a>(img_rgb, cv.COLOR_BGR2GRAY)</div><div class="line">template = <a class="code" href="../../d4/da8/group__imgcodecs.html#ga288b8b3da0892bd651fce07b3bbd3a56">cv.imread</a>(<span class="stringliteral">&#39;mario_coin.png&#39;</span>,0)</div><div class="line">w, h = template.shape[::-1]</div><div class="line"></div><div class="line">res = <a class="code" href="../../df/dfb/group__imgproc__object.html#ga586ebfb0a7fb604b35a23d85391329be">cv.matchTemplate</a>(img_gray,template,cv.TM_CCOEFF_NORMED)</div><div class="line">threshold = 0.8</div><div class="line">loc = np.where( res &gt;= threshold)</div><div class="line"><span class="keywordflow">for</span> pt <span class="keywordflow">in</span> zip(*loc[::-1]):</div><div class="line">    <a class="code" href="../../d6/d6e/group__imgproc__draw.html#gac865734d137287c0afb7682ff7b3db23">cv.rectangle</a>(img_rgb, pt, (pt[0] + w, pt[1] + h), (0,0,255), 2)</div><div class="line"></div><div class="line"><a class="code" href="../../d4/da8/group__imgcodecs.html#gabbc7ef1aa2edfaa87772f1202d67e0ce">cv.imwrite</a>(<span class="stringliteral">&#39;res.png&#39;</span>,img_rgb)</div></div><!-- fragment --><p> Result:</p>
<div class="image">
<img src="../../res_mario.jpg" alt="res_mario.jpg"/>
<div class="caption">
image</div></div>
 <h2>Additional Resources </h2>
<h2>Exercises </h2>
</div></div><!-- contents -->
<!-- HTML footer for doxygen 1.8.6-->
<!-- start footer part -->
<hr class="footer"/><address class="footer"><small>
Generated on Fri Apr 2 2021 11:36:37 for OpenCV by &#160;<a href="http://www.doxygen.org/index.html">
<img class="footer" src="../../doxygen.png" alt="doxygen"/>
</a> 1.8.13
</small></address>
<script type="text/javascript">
//<![CDATA[
addTutorialsButtons();
//]]>
</script>
</body>
</html>
